home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlb20 / lib / dirent.c < prev    next >
C/C++ Source or Header  |  1992-04-06  |  4KB  |  202 lines

  1. /* opendir/readdir/closedir routines */
  2.  
  3. /* under MiNT (v0.9 or better) these use the appropriate system calls.
  4.  * under TOS or older versions of MiNT, they use Fsfirst/Fsnext
  5.  *
  6.  * Written by Eric R. Smith and placed in the public domain
  7.  */
  8.  
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <types.h>
  12. #include <limits.h>
  13. #include <dirent.h>
  14. #include <errno.h>
  15. #include <osbind.h>
  16. #include <mintbind.h>
  17. #include "lib.h"
  18.  
  19. extern int __mint;
  20. extern ino_t __inode;    /* in stat.c */
  21.  
  22. DIR *
  23. opendir(uname)
  24.     const char *uname;
  25. {
  26.     DIR *d;
  27.     long r, olddta;
  28.     char name[PATH_MAX];
  29.     char dirpath[PATH_MAX];
  30.     char *p;
  31.  
  32.     _unx2dos(uname, name);
  33.  
  34.     if (__mint > 8) {
  35.         r = Dopendir(name, 0);
  36.         if ( (r & 0xff000000) == 0xff000000 ) {
  37.             errno = -r;
  38.             return 0;
  39.         }
  40.         return (DIR *)r;
  41.     }
  42.  
  43. /* TOS emulation routines */
  44.  
  45.     d = malloc(sizeof(DIR));
  46.     if (!d) {
  47.         errno = ENOMEM;
  48.         return d;
  49.     }
  50.  
  51.     for (p = name; *p; p++) ;
  52.     --p;
  53.     if (*p != '\\')
  54.         *++p = '\\';
  55.  
  56.     strcpy(p, "*.*");
  57.     olddta = Fgetdta();
  58.     Fsetdta(d->dta);
  59.     r = Fsfirst(name, 0x17);
  60.     Fsetdta(olddta);
  61.  
  62.     if (r == 0) {
  63.         d->status = _STARTSEARCH;
  64.     } else if (r == -ENOENT) {
  65.         d->status = _NMFILE;
  66.     } else {
  67.         free(d);
  68.         errno = -r;
  69.         return 0;
  70.     }
  71.     d->buf.d_off = 0;
  72. /* for rewinddir: if necessary, build a relative path */
  73.     if (name[1] == ':') {    /* absolute path, no problem */
  74.         dirpath[0] = 0;
  75.     } else {
  76.         dirpath[0] = Dgetdrv() + 'A';
  77.         dirpath[1] = ':';
  78.         dirpath[2] = 0;
  79.         if (*name != '\\')
  80.             (void)Dgetpath(dirpath+2, 0);
  81.     }
  82.     d->dirname = malloc(strlen(dirpath)+strlen(name)+1);
  83.     if (d->dirname) {
  84.         strcpy(d->dirname, dirpath);
  85.         strcat(d->dirname, name);
  86.     }
  87.     return d;
  88. }
  89.  
  90. struct dirent *
  91. readdir(d)
  92.     DIR *d;
  93. {
  94.     struct dbuf {
  95.         long ino;
  96.         char name[NAME_MAX + 1];
  97.     } dbuf;
  98.     long r, olddta;
  99.     struct dirent *dd = &d->buf;
  100.  
  101.     if (__mint > 8) {
  102.         r = Dreaddir(NAME_MAX+1+sizeof(long), d, &dbuf);
  103.         if (r == -ENMFIL)
  104.             return 0;
  105.         else if (r) {
  106.             errno = -r;
  107.             return 0;
  108.         }
  109.         dd->d_ino = dbuf.ino;
  110.         dd->d_off++;
  111.         dd->d_reclen = strlen(dbuf.name);
  112.         strcpy(dd->d_name, dbuf.name);
  113.         return dd;
  114.     }
  115. /* ordinary TOS search, using Fsnext. Note that the first time through,
  116.  * Fsfirst has already provided valid data for us; for subsequent
  117.  * searches, we need Fsnext.
  118.  */
  119.     if (d->status == _NMFILE)
  120.         return 0;
  121.     if (d->status == _STARTSEARCH) {
  122.         d->status = _INSEARCH;
  123.     } else {
  124.         olddta = Fgetdta();
  125.         Fsetdta(d->dta);
  126.         r = Fsnext();
  127.         Fsetdta(olddta);
  128.         if (r == -ENMFIL) {
  129.             d->status = _NMFILE;
  130.             return 0;
  131.         } else if (r) {
  132.             errno = -r;
  133.             return 0;
  134.         }
  135.     }
  136.     dd->d_ino = __inode++;
  137.     dd->d_off++;
  138.     _dos2unx(d->dta+30, dd->d_name);
  139.     dd->d_reclen = strlen(dd->d_name);
  140.     return dd;
  141. }
  142.  
  143. void
  144. rewinddir(dirp)
  145.     DIR *dirp;
  146. {
  147.     long r, olddta;
  148.  
  149.     if (__mint >= 9) {
  150.         (void)Drewinddir(dirp);
  151.         return;
  152.     }
  153.  
  154. /* I wish POSIX had allowed an error to occur here! */
  155.     if (!dirp->dirname) {
  156.         return;
  157.     }
  158.  
  159.     olddta = Fgetdta();
  160.     Fsetdta(dirp->dta);
  161.     r = Fsfirst(dirp->dirname, 0x17);
  162.     Fsetdta(olddta);
  163.     if (r == 0) {
  164.         dirp->status = _STARTSEARCH;
  165.     } else {
  166.         dirp->status = _NMFILE;
  167.     }
  168.     dirp->buf.d_off = 0;
  169. }
  170.  
  171. int
  172. closedir(dirp)
  173.     DIR *dirp;
  174. {
  175.     if (__mint > 8) {
  176.         return Dclosedir(dirp);
  177.     }
  178.     free(dirp);
  179.     return 0;
  180. }
  181.  
  182. /* the next two aren't POSIX, but lots of people have them */
  183.  
  184. off_t
  185. telldir(dirp)
  186.     DIR *dirp;
  187. {
  188.     return dirp->buf.d_off;
  189. }
  190.  
  191. void
  192. seekdir(dirp, loc)
  193.     DIR *dirp;
  194.     off_t loc;
  195. {
  196.     rewinddir(dirp);
  197.     while (dirp->buf.d_off != loc) {
  198.         if (!readdir(dirp))
  199.             break;
  200.     }
  201. }
  202.